Option Explicit

'################################################################
' 池化对象工具
'################################################################

'################################################################
' Field
'################################################################
'----------------------------------------------------
' 用来保存各种类型的池化数据的缓存
'----------------------------------------------------
' ObjStack 类型的池
Private objStackPool As IObjArrayRef

' PrimitiveStack 类型的池
Private primitiveStackPool As IObjArrayRef

' Set 类型的池
' 默认使用 HashSet
Private baseSetPool As IObjArrayRef

' LinkedHashSet 类型的池
Private linkedSetPool As IObjArrayRef

' IObjArrayRef 类型的池
' 如何保存
' Map<长度, 对象>
' 但是长度有可能会相同
' 1 --> ref1 ref2
' ^
' 2 --> ref1
' ^
' 4 --> ref1
' ^
' 5 --> ref1 ref2 ref3
' 可以大不能小，但是也不能太大
' MultiObjLinkedMap
' ObjArrayRefPool
' save ref1
' 按照数组的实际长度保存
'
' Private objArrayRefPool As Object

'################################################################
' Public
'################################################################
'----------------------------------------------------
' 清空池数据
'----------------------------------------------------
' 清空所有类型的池数据
Public Sub clearAllPool()
    Set objStackPool = Nothing
    Set primitiveStackPool = Nothing
    Set baseSetPool = Nothing
    Set linkedSetPool = Nothing
End Sub

'----------------------------------------------------
' ObjStack 类型的池的操作
'----------------------------------------------------
' 尝试从对象池中获取一个 ObjStack 型数据
' 如果池中没有可用数据，则手动创建一个对象并返回
Public Function getObjStack() As ObjStack
    If objStackPool Is Nothing Then
        ' 如果池对象还没有创建，则手动创建一个对象
        ' 这里不创建池对象，延迟到 release 方法中再创建
        Set getObjStack = New ObjStack
    Else
        If objStackPool.Count = 0 Then
            ' 如果池对象已经创建，但是池中没有可用内容，则手动创建一个对象
            Set getObjStack = New ObjStack
        Else
            ' 如果池对象中存在可用内容，则从末尾拉取一个数据
            Set getObjStack = objStackPool.pollLast
        End If
    End If
End Function

' 将一个 ObjStack 型数据释放回池中
Public Sub releaseObjStack(ByRef d As ObjStack)
    ' 如果参数为空对象，则退出处理
    If d Is Nothing Then
        Exit Sub
    End If

    If objStackPool Is Nothing Then
        ' 如果池对象还没有创建，则手动创建一个对象
        Set objStackPool = UtilsArrayRef.createRealObjArrayRef
    End If

    ' 清空栈并保存到池对象内
    d.clear

    objStackPool.Add d
End Sub

'----------------------------------------------------
' PrimitiveStack 类型的池的操作
'----------------------------------------------------
' 尝试从对象池中获取一个 PrimitiveStack 型数据
' 如果池中没有可用数据，则手动创建一个对象并返回
Public Function getPrimitiveStack() As PrimitiveStack
    If primitiveStackPool Is Nothing Then
        ' 如果池对象还没有创建，则手动创建一个对象
        ' 这里不创建池对象，延迟到 release 方法中再创建
        Set getPrimitiveStack = New PrimitiveStack
    Else
        If primitiveStackPool.Count = 0 Then
            ' 如果池对象已经创建，但是池中没有可用内容，则手动创建一个对象
            Set getPrimitiveStack = New PrimitiveStack
        Else
            ' 如果池对象中存在可用内容，则从末尾拉取一个数据
            Set getPrimitiveStack = primitiveStackPool.pollLast
        End If
    End If
End Function

' 将一个 PrimitiveStack 型数据释放回池中
Public Sub releasePrimitiveStack(ByRef d As PrimitiveStack)
    ' 如果参数为空对象，则退出处理
    If d Is Nothing Then
        Exit Sub
    End If

    If primitiveStackPool Is Nothing Then
        ' 如果池对象还没有创建，则手动创建一个对象
        Set primitiveStackPool = UtilsArrayRef.createRealObjArrayRef
    End If

    ' 清空栈并保存到池对象内
    d.clear

    primitiveStackPool.Add d
End Sub

'----------------------------------------------------
' 基础 Set 对象池
'----------------------------------------------------
' 尝试从对象池中获取一个 ISet 对象，默认返回 HashSet 类型的数据
' 如果池中没有可用数据，则手动创建一个 HashSet 对象并返回
Public Function getSet() As ISet
    If baseSetPool Is Nothing Then
        ' 如果池对象还没有创建，则手动创建一个对象
        Set getSet = UtilsSet.createHashSet
    Else
        If baseSetPool.Count = 0 Then
            ' 如果池对象已经创建，但是池中没有可用内容，则手动创建一个对象
            Set getSet = UtilsSet.createHashSet
        Else
            ' 如果池对象中存在可用内容，则从末尾拉取一个数据
            Set getSet = baseSetPool.pollLast
        End If
    End If
End Function

' 将一个 ISet 型数据释放回池中
Public Sub releaseSet(ByRef d As ISet)
    ' 如果参数为空对象，则退出处理
    If d Is Nothing Then
        Exit Sub
    End If

    If baseSetPool Is Nothing Then
        ' 如果池对象还没有创建，则手动创建一个对象
        Set baseSetPool = UtilsArrayRef.createRealObjArrayRef
    End If

    ' 清空栈并保存到池对象内
    d.Clear

    baseSetPool.Add d
End Sub

'----------------------------------------------------
' LinkedHashSet 对象池
'----------------------------------------------------
' 尝试从对象池中获取一个 ISet 对象，默认返回 LinkedHashSet 类型的数据
' 如果池中没有可用数据，则手动创建一个 LinkedHashSet 对象并返回
Public Function getLinkedSet() As ISet
    If linkedSetPool Is Nothing Then
        ' 如果池对象还没有创建，则手动创建一个对象
        Set getLinkedSet = UtilsSet.createLinkedHashSet
    Else
        If linkedSetPool.Count = 0 Then
            ' 如果池对象已经创建，但是池中没有可用内容，则手动创建一个对象
            Set getLinkedSet = UtilsSet.createLinkedHashSet
        Else
            ' 如果池对象中存在可用内容，则从末尾拉取一个数据
            Set getLinkedSet = linkedSetPool.pollLast
        End If
    End If
End Function

' 将一个 ISet 型数据释放回池中
Public Sub releaseLinkedSet(ByRef d As ISet)
    ' 如果参数为空对象，则退出处理
    If d Is Nothing Then
        Exit Sub
    End If

    If linkedSetPool Is Nothing Then
        ' 如果池对象还没有创建，则手动创建一个对象
        Set linkedSetPool = UtilsArrayRef.createRealObjArrayRef
    End If

    ' 清空栈并保存到池对象内
    d.Clear

    linkedSetPool.Add d
End Sub

' '----------------------------------------------------
' ' IObjArrayRef 类型的池的操作
' '----------------------------------------------------
' ' 尝试从对象池中获取一个 IObjArrayRef 型数据
' ' 如果池中没有可用数据，则手动创建一个对象并返回
' Public Function getgetObjArrayRef(Optional ByRef arrSize As Long = 10) As IObjArrayRef
'     If objArrayRefPool Is Nothing Then
'         ' 如果池对象还没有创建，则手动创建一个对象
'         Set getObjArrayRef = UtilsArrayRef.createRealObjArrayRef(arrSize)
'     Else
'         If objStackPool.Count = 0 Then
'             ' 如果池对象已经创建，但是池中没有可用内容，则手动创建一个对象
'             Set getObjArrayRef = UtilsArrayRef.createRealObjArrayRef(arrSize)
'         Else
'             ' 如果池对象中存在可用内容，则从末尾拉取一个数据
'             ' TODO
'         End If
'     End If
' End Function
' 
' ' 将一个 IObjArrayRef 型数据释放回池中
' Public Sub releaseObjArrayRef(ByRef d As IObjArrayRef)
'     If objArrayRefPool Is Nothing Then
'         ' TODO
'     End If
' 
'     ' 清空栈并保存到池对象内
'     d.clear
' 
'     objArrayRefPool.Add d
' End Sub
